home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
bipl.zip
/
PROCS.ZIP
/
MATH.ICN
< prev
next >
Wrap
Text File
|
1992-09-28
|
7KB
|
239 lines
############################################################################
#
# File: math.icn
#
# Subject: Procedures to perform mathematical computations
#
# Author: George D. Yee
#
# Date: June 10, 1988
#
###########################################################################
#
# Note:
# Version 8 of Icon supports most of the procedures that follow as
# built-in functions. The procedures here should not be used unless the
# corresponding functions are disabled.
#
############################################################################
#
# The following procedures compute standard trigonometric func-
# tions. The arguments are in radians.
#
# sin(x) sine of x
#
# cos(x) cosine of x
#
# tan(x) tangent of x
#
# asin(x) arc sine of x in the range -pi/2 to pi/2
#
# acos(x) arc cosine of x in the range 0 to pi
#
# atan(x) arc tangent of x in the range -pi/2 to pi/2
#
# atan2(y,x) arc tangent of x/y in the range -pi to pi
#
# The following procedures convert from degrees to radians and con-
# versely:
#
# dtor(d) radian equivalent of d
#
# rtod(r) degree equivalent of r
#
# The following additional procedures are available:
#
# sqrt(x) square root of x
#
# exp(x) exponential function of x
#
# log(x) natural logarithm of x
#
# log10(x) base-10 logarithm of x
#
# floor(x) largest integer not greater than x
#
# ceil(x) smallest integer nor less than x
#
# Failure Conditions: asin(x) and acos(x) fail if the absolute
# value of x is greater than one. sqrt(x), log(x), and log10(x)
# fail if x is less than zero.
#
############################################################################
procedure sin(x)
return _sinus(numeric(x),0)
end
procedure cos(x)
return _sinus(abs(numeric(x)),1)
end
procedure tan(x)
return sin(x) / (0.0 ~= cos(x))
end
# atan returns the value of the arctangent of its
# argument in the range [-pi/2,pi/2].
procedure atan(x)
if numeric(x) then
return if x > 0.0 then _satan(x) else -_satan(-x)
end
# atan2 returns the arctangent of y/x
# in the range [-pi,pi].
procedure atan2(y,x)
local r
static pi
initial pi := 3.141592653589793238462643
return if numeric(y) & numeric(x) then {
if x > 0.0 then
atan(y/x)
else if x < 0.0 then {
r := pi - atan(abs(y/x))
if y >= 0.0 then r else -r
}
else if x = y = 0.0 then
0.0 # special value if both x and y are zero
else
if y >= 0.0 then pi/2.0 else -pi/2.0
}
end
procedure asin(x)
if abs(numeric(x)) <= 1.0 then
return atan2(x, (1.0-(x^2))^0.5)
end
procedure acos(x)
return 1.570796326794896619231e0 - asin(x)
end
procedure dtor(deg)
return numeric(deg)/57.29577951308232
end
procedure rtod(rad)
return numeric(rad)*57.29577951308232
end
procedure sqrt(x)
return (0.0 <= numeric(x)) ^ 0.5
end
procedure floor(x)
return if numeric(x) then
if x>=0.0 | real(x)=integer(x) then integer(x) else -integer(-x+1)
end
procedure ceil(x)
return -floor(-numeric(x))
end
procedure log(x)
local z, zsq, ex
static log2, sqrto2, p0, p1, p2, p3, q0, q1, q2
initial {
# The coefficients are #2705 from Hart & Cheney. (19.38D)
log2 := 0.693147180559945309e0
sqrto2 := 0.707106781186547524e0
p0 := -0.240139179559210510e2
p1 := 0.309572928215376501e2
p2 := -0.963769093368686593e1
p3 := 0.421087371217979714e0
q0 := -0.120069589779605255e2
q1 := 0.194809660700889731e2
q2 := -0.891110902798312337e1
}
if numeric(x) > 0.0 then {
ex := 0
while x >= 1.0 do {
x /:= 2.0
ex +:= 1
}
while x < 0.5 do {
x *:= 2.0
ex -:= 1
}
if x < sqrto2 then {
x *:= 2.0
ex -:= 1
}
return ((((p3*(zsq:=(z:=(x-1.0)/(x+1.0))^2)+p2)*zsq+p1)*zsq+p0)/
(((1.0*zsq+q2)*zsq+q1)*zsq+q0))*z+ex*log2
}
end
procedure exp(x)
return 2.718281828459045235360287 ^ numeric(x)
end
procedure log10(x)
return log(x)/2.30258509299404568402
end
procedure _sinus(x,quad)
local ysq, y, k
static twoopi, p0, p1, p2, p3, p4, q0, q1, q2, q3
initial {
# Coefficients are #3370 from Hart & Cheney (18.80D).
twoopi := 0.63661977236758134308
p0 := 0.1357884097877375669092680e8
p1 := -0.4942908100902844161158627e7
p2 := 0.4401030535375266501944918e6
p3 := -0.1384727249982452873054457e5
p4 := 0.1459688406665768722226959e3
q0 := 0.8644558652922534429915149e7
q1 := 0.4081792252343299749395779e6
q2 := 0.9463096101538208180571257e4
q3 := 0.1326534908786136358911494e3
}
if x < 0.0 then {
x := -x
quad +:= 2
}
y := (x *:= twoopi) - (k := integer(x))
if (quad := (quad + k) % 4) = (1|3) then
y := 1.0 - y
if quad > 1 then
y := -y
return (((((p4*(ysq:=y^2)+p3)*ysq+p2)*ysq+p1)*ysq+p0)*y) /
((((ysq+q3)*ysq+q2)*ysq+q1)*ysq+q0)
end
procedure _satan(x)
static sq2p1,sq2m1,pio2,pio4
initial {
sq2p1 := 2.414213562373095048802e0
sq2m1 := 0.414213562373095048802e0
pio2 := 1.570796326794896619231e0
pio4 := 0.785398163397448309615e0
}
return if x < sq2m1 then
_xatan(x)
else if x > sq2p1 then
pio2 - _xatan(1.0/x)
else
pio4 + _xatan((x-1.0)/(x+1.0))
end
procedure _xatan(x)
local xsq
static p4,p3,p2,p1,p0,q4,q3,q2,q1,q0
initial {
# coefficients are #5077 from Hart & Cheney. (19.56D)
p4 := 0.161536412982230228262e2
p3 := 0.26842548195503973794141e3
p2 := 0.11530293515404850115428136e4
p1 := 0.178040631643319697105464587e4
p0 := 0.89678597403663861959987488e3
q4 := 0.5895697050844462222791e2
q3 := 0.536265374031215315104235e3
q2 := 0.16667838148816337184521798e4
q1 := 0.207933497444540981287275926e4
q0 := 0.89678597403663861962481162e3
}
return x * ((((p4*(xsq:=x^2)+p3)*xsq+p2)*xsq+p1)*xsq+p0) /
(((((xsq+q4)*xsq+q3)*xsq+q2)*xsq+q1)*xsq+q0)
end